package com.ljp.makefriend.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.ljp.makefriend.WebSocket.pojo.ResultMessage;
import com.ljp.makefriend.common.ErrorCode;
import com.ljp.makefriend.exception.BusinessException;
import com.ljp.makefriend.pojo.ChatMessages;

import com.ljp.makefriend.mapper.ChatMessagesMapper;
import com.ljp.makefriend.pojo.User;
import com.ljp.makefriend.pojo.vo.ChatMessagesVo;
import com.ljp.makefriend.service.ChatMessagesService;
import com.ljp.makefriend.service.UserService;
import org.springframework.beans.BeanUtils;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.List;

/**
* @author admin
* @description 针对表【chat_messages(用户私聊消息表)】的数据库操作Service实现
* @createDate 2024-10-29 18:58:02
*/
@Service
public class ChatMessagesServiceImpl extends ServiceImpl<ChatMessagesMapper, ChatMessages>
    implements ChatMessagesService {
    // 当前登录用户
    public static User loginUser;

    @Resource
    private UserService userService;

    @Resource
    private RedisTemplate<String, Object> redisTemplate;

    /**
     * 获取历史消息
     *
     * @param senderId   发送用户id
     * @param receiverId 接收用户id
     * @return 历史消息集合
     */
    @Transactional
    @Override
    public List<ChatMessagesVo> getHistoryMessages(long senderId, long receiverId) {
//        1. 参数效验
        if (senderId <= 0 || receiverId <= 0) {
            throw new BusinessException(ErrorCode.PARAMS_ERROR);
        }
//        2. 从数据库中查询已保存的历史消息
        QueryWrapper<ChatMessages> chatMessagesQueryWrapper = new QueryWrapper<>();
        chatMessagesQueryWrapper
                .eq("sender_id",senderId).eq("receiver_id",receiverId)
                .or()
                .eq("receiver_id",senderId).eq("sender_id",receiverId);
        List<ChatMessages> chatMessagesFromSQL = this.list(chatMessagesQueryWrapper);

//        4. 从缓存中获取历史消息
        List<ChatMessages> chatMessagesFromCache = this.getChatMessagesFromCache(senderId, receiverId);

//        7. 设置消息返回内容
        if (!chatMessagesFromCache.isEmpty()) {
            chatMessagesFromSQL.addAll(chatMessagesFromCache);
        }
        List<ChatMessagesVo> chatMessagesVoList = new ArrayList<>();
        chatMessagesFromSQL.forEach(chatMessages -> {
            // 根据 id 获取发消息用户
            User senderUser = userService.getById(chatMessages.getSenderId());
            // 设置发送消息的用户头像
            String senderUserAvatar = senderUser.getAvatarUrl();
            ChatMessagesVo chatMessagesVo = new ChatMessagesVo();
            chatMessagesVo.setSenderId(chatMessages.getSenderId()); // 发送者 id
            chatMessagesVo.setReceiverId(String.valueOf(chatMessages.getReceiverId())); // 接收者 id
            chatMessagesVo.setAvatar(senderUserAvatar); // 发送者头像
            chatMessagesVo.setMessage(chatMessages.getMessage());   // 发送消息内容
            chatMessagesVo.setTimestamp(chatMessages.getTimestamp());   // 发送时间
            chatMessagesVo.setReadStatus(1);    // 标记消息为已读
            chatMessagesVoList.add(chatMessagesVo);
        });
//        8. 返回历史消息集合
        // 根据时间升序排序返回
        return chatMessagesVoList.stream()
                .sorted((c1, c2) -> {
                    long time = c1.getTimestamp().getTime() - c2.getTimestamp().getTime();
                    if (time == 0) return 0;
                    if (time > 0) return 1;
                    return -1;
                }).toList();
    }

    /**
     * 获取最新一条的消息
     *
     * @param senderUser   s
     * @param receiverUser r
     * @return 用户之间最新的一条消息
     */
    @Override
    public ChatMessages getOneNewMessage(User senderUser, User receiverUser) {
        if (senderUser == null || receiverUser == null ) {
            throw new BusinessException(ErrorCode.PARAMS_ERROR);
        }
        // 发送者id
        long senderUserId = senderUser.getId();
        // 接收者id
        long receiverUserId = receiverUser.getId();
        // 从数据库中获取消息状态
        boolean SQLIsEmpty = false;
        QueryWrapper<ChatMessages> messagesQueryWrapper = new QueryWrapper<>();
        messagesQueryWrapper
                .eq("sender_id", senderUserId).eq("receiver_id", receiverUserId)
                .or()
                .eq("sender_id", receiverUserId).eq("receiver_id", senderUserId);
        messagesQueryWrapper.orderByDesc("timestamp"); // 根据时间降序排序
        List<ChatMessages> chatMessagesFromSQL = this.list(messagesQueryWrapper);
        if (chatMessagesFromSQL == null || chatMessagesFromSQL.isEmpty()) {
            SQLIsEmpty = true;
        }
        // 从 Redis 缓存中获取消息
        List<ChatMessages> chatMessagesFromCache = this.getChatMessagesFromCache(senderUserId, receiverUserId);
        // 数据库与缓存中都没有消息
        if (chatMessagesFromCache.isEmpty() && SQLIsEmpty) {
            return null;
        }
        List<ChatMessages> chatMessagesList = new ArrayList<>();
        assert chatMessagesFromSQL != null;
        chatMessagesList.addAll(chatMessagesFromSQL);
        chatMessagesList.addAll(chatMessagesFromCache);
        // 消息根据发送时间进行降序
        List<ChatMessages> resultMessageList = chatMessagesList.stream()
                .sorted((c1, c2) -> {
                    long time = c2.getTimestamp().getTime() - c1.getTimestamp().getTime();
                    if (time == 0) return 0;
                    if (time > 0) return 1;
                    return -1;
                }).toList();
        if (resultMessageList.isEmpty()) {
            return null;
        }
        return resultMessageList.get(0);
    }

    /**
     * 修改用户之间的消息读取状态
     * @param senderId 发送者 id
     * @param receiverId    接收者 id（查看）
     * @return  true - 修改用户已读消息状态
     */
    @Override
    public boolean updateReadStatus(long senderId, long receiverId) {
        // 当缓存中的消息还未持久化到数据库的时候，此时需要更新缓存中消息的读取状态
        QueryWrapper<ChatMessages> messagesQueryWrapper = new QueryWrapper<>();
        ChatMessages chatMessages = new ChatMessages();
        // 当接收者消息查看消息后才执行后续操作
        // 1、更新数据库中的消息状态
        long loginUserId = loginUser.getId();
        if (loginUserId != receiverId) {
            return false;
        }
        messagesQueryWrapper
                .eq("sender_id",senderId).eq("receiver_id",receiverId)
                .ne("read_status",0)
                .or()
                .eq("sender_id",receiverId).eq("receiver_id",senderId)
                .ne("read_status",0);
        chatMessages.setReadStatus(0);
        List<ChatMessages> chatMessages1 = list(messagesQueryWrapper);
        if (!chatMessages1.isEmpty()) {
            this.update(chatMessages, messagesQueryWrapper);
        }

        // 2、更新缓存中的消息状态
        // 获取缓存中的消息
        String key1 = "chat_message:sender_id:" + senderId + ":receiver_id:" + receiverId;
        String key2 = "chat_message:sender_id:" + receiverId + ":receiver_id:" + senderId;
        // 从缓存中获取历史消息
        List<ChatMessages> cacheChatMessage = this.getChatMessagesFromCache(senderId,receiverId);
        if (cacheChatMessage.isEmpty()) {
            return true;
        }
        // 先清空旧的缓存消息数据
        redisTemplate.delete(key1);
        redisTemplate.delete(key2);
        //更新缓存中的消息状态,并插入缓存
        for (ChatMessages cacheMessage: cacheChatMessage) {
            String key = "chat_message:sender_id:" + cacheMessage.getSenderId()
                    + ":receiver_id:" + cacheMessage.getReceiverId();
            if (cacheMessage.getReadStatus() == null ||
                    (cacheMessage.getReadStatus() == 1 && cacheMessage.getReceiverId().equals(receiverId))) {
                cacheMessage.setReadStatus(0);
            }
            // 插入缓存
            ResultMessage resultMessage = new ResultMessage();
            BeanUtils.copyProperties(cacheMessage, resultMessage);
            redisTemplate.opsForList().rightPush(key, resultMessage);
            }
        return true;
    }


    /**
     * 获取缓存中的信息记录
     *
     * @param senderId        发送者 id
     * @param receiverId      接收者 id
     * @return 缓存中的消息
     */
    private List<ChatMessages> getChatMessagesFromCache
            (long senderId,long receiverId) {
        List<ChatMessages> chatMessagesList = new ArrayList<>();
        // 通过 key 获取是否有缓存消息
        Long size1 = redisTemplate.opsForList()
                .size("chat_message:sender_id:" + senderId + ":receiver_id:" + receiverId);
        Long size2 = redisTemplate.opsForList()
                .size("chat_message:sender_id:" + receiverId + ":receiver_id:" + senderId);
        if ((size1 != null && size1 > 0) || (size2 != null && size2 > 0)) {
            List<Object> SToR_Messages = redisTemplate.opsForList()
                    .range("chat_message:sender_id:" + senderId + ":receiver_id:" + receiverId, 0, size1);
            List<Object> RToS_Messages = redisTemplate.opsForList()
                    .range("chat_message:sender_id:" + receiverId + ":receiver_id:" + senderId, 0, size2);
            // 缓存中有消息
            // 取出消息
            assert SToR_Messages != null;
            for (Object SToR_Message : SToR_Messages) {
                ChatMessages chatMessage = new ChatMessages();
                ResultMessage resultMsg = (ResultMessage) SToR_Message;
                BeanUtils.copyProperties(resultMsg, chatMessage);
                chatMessagesList.add(chatMessage);
            }
            assert RToS_Messages != null;
            for (Object RToS_Message: RToS_Messages) {
                ChatMessages chatMessage = new ChatMessages();
                ResultMessage resultMsg = (ResultMessage) RToS_Message;
                BeanUtils.copyProperties(resultMsg, chatMessage);
                chatMessagesList.add(chatMessage);
            }
        }
        if (!chatMessagesList.isEmpty()) {
            return chatMessagesList;
        }
        return new ArrayList<>();
    }
}




